import {_decorator, Component, find, instantiate, Node, Prefab, Vec3} from 'cc';
import {BLOCK_SIZE, PlayerController} from "db://assets/Scripts/Player/PlayerController";
import {BlockType} from "db://assets/Scripts/Player/BlockType";
import {GameState} from "db://assets/Scripts/Game/GameState";
import {UIPaths} from "db://assets/Scripts/Common/UIPaths";
import {EventManager} from "db://assets/Scripts/Common/EventManager";
import {EventType} from "db://assets/Scripts/Common/EventType";
import {App} from "db://assets/Scripts/Common/App";

const {ccclass, property} = _decorator;

@ccclass('GameManager')
export class GameManager extends Component {
    /**
     * 开始菜单
     */
    @property(Node)
    public startMenu: Node = null!;
    /**
     * 角色控制器
     */
    public playerController: PlayerController = null!;

    /**
     * 方块预制体
     */
    @property({type: Prefab})
    public boxPrefab: Prefab = null!;

    /**
     * 路的数据
     */
    private road: BlockType[] = [];
    /**
     * 结算界面
     */
    private endPlane: Node = null!;

    onLoad() {
        // 结算界面
        this.endPlane = find(UIPaths.END_PLANE);
        // 主角
        this.playerController = find(UIPaths.PLAYER).getComponent(PlayerController);
    }

    onEnable() {
        // 监听更新分数事件
        EventManager.on(EventType.SCORE, this.updateScore, this);
    }

    onDisable() {
        // 取消监听更新分数事件
        EventManager.off(EventType.SCORE, this.updateScore, this);
    }

    start() {
        // 设置游戏状态
        this.setGameState(GameState.INIT);
    }

    /**
     * 设置游戏状态
     *
     * @param state 游戏状态
     */
    setGameState(state: GameState) {
        switch (state) {
            case GameState.INIT:
                this.init();
                break;
            case GameState.PLAYING:
                this.playing();
                break;
            case GameState.END:
                this.end();
                break;
        }
    }

    /**
     * 游戏初始化
     */
    private init() {
        // 显示菜单
        this.startMenu.active = true;

        // 生成地图
        this.generateRoad();

        // 激活鼠标监听事件
        this.playerController.setInputActive(false);
        // 重置角色初始位置
        this.playerController.node.setPosition(Vec3.ZERO);
        // 重置角色控制器
        this.playerController.reset();
    }

    /**
     * 游戏中
     */
    private playing() {
        // 隐藏菜单
        this.startMenu.active = false;

        // 重置分数
        EventManager.emit(EventType.SCORE, 0);

        // 直接设置 active 会直接开始监听鼠标事件，做了一下延迟处理
        setTimeout(() => {
            this.playerController.setInputActive(true);
        }, 0.1);
    }

    /**
     * 游戏结束
     */
    private end() {
        // 游戏结束，可以显示结算界面
        this.endPlane.active = true;
    }

    /**
     * 游戏开始按钮
     */
    onStartButtonClickListener() {
        this.setGameState(GameState.PLAYING);
    }

    /**
     * 监听更新分数事件
     *
     * @param score 分数
     */
    updateScore(score: number) {
        // 检测游戏是否结束
        this.checkResult(score);
    }

    /**
     * 用于判定角色是否跳跃到坑或者跳完所有地块的方法
     *
     * @param moveIndex 当前角色所处位置
     */
    checkResult(moveIndex: number) {
        if (moveIndex < App.ROAD_LENGTH) {
            if (this.road[moveIndex] === BlockType.NONE) {
                this.setGameState(GameState.END);
            }
        } else {
            this.setGameState(GameState.END);
        }
    }

    update(deltaTime: number) {

    }

    /**
     * 每次生成时，需要将上次的结果清除
     * 第一个地块永远是方块，保证角色不会掉下去
     * 由于我们的角色可以选择跳 1 个方块或者 2 个方块，因此坑最多不应该连续超过 2 个，也就意味着如果前面 1 个地块是坑，那么接下来的地块必须是方块
     */
    generateRoad() {
        // 每次生成时，需要将上次的结果清除
        this.node.removeAllChildren();
        this.road = [];

        // 第一个地块永远是方块，保证角色不会掉下去
        this.road.push(BlockType.STONE);

        for (let i = 1; i < App.ROAD_LENGTH; i++) {
            // 由于我们的角色可以选择跳 1 个方块或者 2 个方块，
            // 因此坑最多不应该连续超过 2 个，也就意味着如果前面 1 个地块是坑，那么接下来的地块必须是方块
            if (this.road[i - 1] === BlockType.NONE) {
                this.road.push(BlockType.STONE);
            } else {
                this.road.push(Math.floor(Math.random() * 2));
            }
        }

        for (let i = 0; i < App.ROAD_LENGTH; i++) {
            let block: Node | null = this.spawnBlockByType(this.road[i]);
            if (block) {
                this.node.addChild(block);
                block.setPosition(i * BLOCK_SIZE, 0, 0);
            }
        }
    }

    /**
     * 生产方块
     *
     * @param blockType 方块类型
     */
    spawnBlockByType(blockType: BlockType): Node | null {
        // 当方块预制体不存在时
        if (!this.boxPrefab) {
            return null;
        }

        // 当为坑时
        if (blockType === BlockType.NONE) {
            return null;
        }

        // 当为方块时
        return instantiate(this.boxPrefab);
    }
}